﻿using Newtonsoft.Json;

namespace PmSoft.Data.Abstractions;

/// <summary>
/// 分页实体标识符集合
/// </summary>
[Serializable]
public class PagedEntityIdsCollection<TKey> where TKey : notnull
{
	/// <summary>
	/// 实体标识符集合
	/// </summary>
	public List<TKey> PagedIds { get; set; } = new List<TKey>();

	/// <summary>
	/// 是否包含多页数据
	/// </summary>
	public bool HasMultiplePages { get; set; }

	/// <summary>
	/// 总记录数
	/// </summary>
	public int TotalRecords { get; set; }

	/// <summary>
	/// 当前集合数量
	/// </summary>
	[JsonIgnore]
	public int Count => PagedIds?.Count ?? 0;

	/// <summary>
	/// 构造函数
	/// </summary>
	public PagedEntityIdsCollection() { }

	/// <summary>
	/// 构造函数
	/// </summary>
	/// <param name="pagedIds">分页实体标识符集合</param>
	public PagedEntityIdsCollection(IEnumerable<TKey> pagedIds)
	{
		TotalRecords = -1;
		PagedIds = pagedIds?.ToList() ?? new List<TKey>();
	}

	/// <summary>
	/// 构造函数
	/// </summary>
	/// <param name="pagedIds">分页实体标识符集合</param>
	/// <param name="totalRecords">总记录数</param>
	public PagedEntityIdsCollection(IEnumerable<TKey> pagedIds, int totalRecords)
	{
		PagedIds = pagedIds?.ToList() ?? new List<TKey>();
		TotalRecords = totalRecords;
	}

	/// <summary>
	/// 获取分页实体标识符集合
	/// </summary>
	/// <param name="pageSize">页大小</param>
	/// <param name="pageIndex">页码（从1开始）</param>
	public IEnumerable<TKey> GetPagedIds(int pageSize, int pageIndex)
	{
		if (PagedIds == null || PagedIds.Count == 0)
			return Enumerable.Empty<TKey>();

		// 参数校验
		pageIndex = pageIndex < 1 ? 1 : pageIndex;
		var startIndex = pageSize * (pageIndex - 1);

		// 索引越界处理
		if (startIndex >= PagedIds.Count)
			return Enumerable.Empty<TKey>();

		// 计算实际取数范围
		var endIndex = pageSize * pageIndex;
		var takeCount = endIndex < PagedIds.Count
			? pageSize
			: PagedIds.Count - startIndex;

		return HasMultiplePages
			? PagedIds
			: PagedIds.GetRange(startIndex, takeCount);
	}

	/// <summary>
	/// 获取前N条实体标识符
	/// </summary>
	/// <param name="topCount">获取数量</param>
	public IEnumerable<TKey> GetTopIds(int topCount)
	{
		if (PagedIds == null || PagedIds.Count == 0)
			return Enumerable.Empty<TKey>();

		var actualCount = topCount > PagedIds.Count
			? PagedIds.Count
			: topCount;

		return PagedIds.GetRange(0, actualCount);
	}
}